float4x4 World;
float4x4 View;
float4x4 Projection;

float3 lightPos;
float lightPower;
float ambientLight;

float wMurk;

Texture Texture0;
Texture Texture1;
Texture Texture2;
Texture Texture3;

sampler TextureSampler0 = sampler_state { texture = <Texture0>; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = wrap; AddressV = wrap; }; 
sampler TextureSampler1 = sampler_state { texture = <Texture1>; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = wrap; AddressV = wrap; }; 
sampler TextureSampler2 = sampler_state { texture = <Texture2>; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = wrap; AddressV = wrap; }; 
sampler TextureSampler3 = sampler_state { texture = <Texture3>; magfilter = LINEAR; minfilter = LINEAR; mipfilter = LINEAR; AddressU = wrap; AddressV = wrap; }; 

struct VertexToPixelMT
{
    float4 Position : POSITION;
    float2 TexCoord	: TEXCOORD0;
    float4 TexWeights : TEXCOORD1;
    float3 Normal	: TEXCOORD2;
    float3 Pos3D	: TEXCOORD3;
};

struct VertexToPixel
{
	float4 Position : POSITION;
	float2 TexCoord : TEXCOORD0;
	float3 Normal : TEXCOORD1;
	float Pos3D : TEXCOORD3;
};

struct PixelToFrameBuff
{
    float4 Color : COLOR0;
};

VertexToPixelMT MultiTextureShader(float4 input : POSITION, float2 texCoords : TEXCOORD0, float4 weights : TEXCOORD1, float3 norm : NORMAL0)
{
    VertexToPixelMT output = (VertexToPixelMT)0;

    float4 worldPosition = mul(input, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);
    
    output.TexCoord = texCoords;
    output.TexWeights = weights;
    
    output.Normal = mul(norm, (float3x3) World);
    output.Pos3D = mul(input, World);

    return output;
}

float DotProduct(float3 pLightPos, float3 pos, float3 normal) {
	float3 lightDir = normalize(pos - pLightPos);
	return dot(-lightDir, normal);
}

PixelToFrameBuff MTPixelShader(VertexToPixelMT PSIn)
{
    PixelToFrameBuff output = (PixelToFrameBuff)0;
    
    float diffuseLight = DotProduct(lightPos, PSIn.Pos3D, PSIn.Normal);
    diffuseLight = saturate(diffuseLight);
    diffuseLight *= lightPower;
    diffuseLight += ambientLight;
	
    output.Color = tex2D(TextureSampler0, PSIn.TexCoord) * PSIn.TexWeights.x;
    output.Color += tex2D(TextureSampler1, PSIn.TexCoord) * PSIn.TexWeights.y;
    output.Color += tex2D(TextureSampler2, PSIn.TexCoord) * PSIn.TexWeights.z;
    output.Color += tex2D(TextureSampler3, PSIn.TexCoord) * PSIn.TexWeights.w;
    
    output.Color.rgb *= diffuseLight;

    return output;
}

technique MultiTextured
{
    pass Pass0
    {
		AlphaBlendEnable	= true;
		SrcBlend			= SrcAlpha;
		DestBlend			= InvSrcAlpha;
		
        VertexShader = compile vs_2_0 MultiTextureShader();
        PixelShader = compile ps_2_0 MTPixelShader();
    }
}

VertexToPixel SingleTextureShader(float4 input : POSITION, float2 texCoords : TEXCOORD0, float3 norm : NORMAL0)
{
    VertexToPixel output = (VertexToPixel)0;

    float4 worldPosition = mul(input, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);
    
    output.TexCoord = texCoords;
    
    output.Normal = mul(norm, (float3x3) World);
    output.Pos3D = mul(input, World);

    return output;
}


PixelToFrameBuff SAPixelShader(VertexToPixel PSIn)
{
    PixelToFrameBuff output = (PixelToFrameBuff)0;
    
    float diffuseLight = DotProduct(lightPos, PSIn.Pos3D, PSIn.Normal);
    diffuseLight = saturate(diffuseLight);
    diffuseLight *= lightPower;
    diffuseLight += ambientLight;
	
    output.Color = tex2D(TextureSampler0, PSIn.TexCoord);
    
    output.Color.rgb *= diffuseLight;

    return output;
}

technique SingleAlphaTexture
{
	pass Pass0
	{
		AlphaBlendEnable	= true;
		SrcBlend			= SrcAlpha;
		DestBlend			= InvSrcAlpha;

		VertexShader = compile vs_2_0 SingleTextureShader();
		PixelShader = compile ps_2_0 SAPixelShader();
	}
}

PixelToFrameBuff WaterPixelShader(VertexToPixel PSIn)
{
    PixelToFrameBuff output = (PixelToFrameBuff)0;
    
    float diffuseLight = DotProduct(lightPos, PSIn.Pos3D, PSIn.Normal);
    diffuseLight = saturate(diffuseLight);
    diffuseLight *= lightPower;
    diffuseLight += ambientLight;
	
    output.Color = tex2D(TextureSampler0, PSIn.TexCoord);
    
    output.Color.rgb *= diffuseLight;
    output.Color.a = 0.7;

    return output;
}

technique WaterShader
{
	pass Pass0
	{
		AlphaBlendEnable	= true;
		SrcBlend			= SrcAlpha;
		DestBlend			= InvSrcAlpha;

		VertexShader = compile vs_2_0 SingleTextureShader();
		PixelShader = compile ps_2_0 WaterPixelShader();
	}
}
